package com.ibeeking.found.open.b.rest.service.impl;

import com.ibeeking.found.common.enums.goods.GoodsChannelEnum;
import com.ibeeking.found.open.api.common.dto.CouponGoodsDTO;
import com.ibeeking.found.open.api.common.dto.OrderAddResultDTO;
import com.ibeeking.found.open.api.common.dto.OrderAmountDTO;
import com.ibeeking.found.open.api.common.dto.OrderChargebackDTO;
import com.ibeeking.found.open.api.common.param.ErpPayTypeParam;
import com.ibeeking.found.open.api.common.param.OrderChargebackParam;
import com.ibeeking.found.open.api.common.param.OrderGoodsParam;
import com.ibeeking.found.open.api.common.query.CouponGoodsQuery;
import com.ibeeking.found.open.api.common.query.ErpOrderGoodsQuery;
import com.ibeeking.found.open.api.common.query.OrderChargebackQuery;
import com.ibeeking.found.open.api.common.query.OrderGoodsQuery;
import com.ibeeking.found.open.api.feign.MarketingFeignClient;
import com.ibeeking.found.open.api.feign.OrderFeignClient;
import com.ibeeking.found.open.b.rest.service.IOrderService;
import com.ibeeking.found.open.b.rest.service.ISystemService;
import com.ibeeking.found.open.service.common.param.OrderAddParam;
import com.ibeeking.found.open.service.common.query.OrderAmountQuery;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.DataUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseCodeEnum;
import com.ibeeking.nematos.utils.result.ResponseResult;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.math.BigDecimal.ROUND_HALF_UP;

/**
 * @ClassName OrderServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-06-15 19:02
 **/
@Service
public class OrderServiceImpl implements IOrderService {

    @Resource
    private OrderFeignClient orderFeignClient;
    @Resource
    private MarketingFeignClient marketingFeignClient;
    @Resource
    private ISystemService systemServiceImpl;

    @Override
    public OrderAmountDTO queryOrderAmount(OrderAmountQuery query) {
        com.ibeeking.found.open.api.common.query.OrderAmountQuery orderAmountQuery = JsonUtils.fromJson(query, com.ibeeking.found.open.api.common.query.OrderAmountQuery.class);
        orderAmountQuery.setMemberId(query.getMemberId());
        orderAmountQuery.setShopId(systemServiceImpl.queryShopIdByShopCode(query.getShopCode()));
        //根据券码和商品查询选中的券码对应的商品关系
        if (null != query.getMemberId() && !Collections3.isEmpty(query.getCouponCodes())) {
            CouponGoodsQuery query1 = new CouponGoodsQuery();
            query1.setMemberId(query.getMemberId());
            query1.setCouponCodes(query.getCouponCodes());
            List<ErpOrderGoodsQuery> erpOrderGoodsQueries = new ArrayList<>();
            query.getGoodsSkus().forEach(s -> {
                ErpOrderGoodsQuery erpOrderGoodsQuery = new ErpOrderGoodsQuery();
                erpOrderGoodsQuery.setChannel(GoodsChannelEnum.POS.getValue());
                erpOrderGoodsQuery.setShopId(orderAmountQuery.getShopId());
                erpOrderGoodsQuery.setGoodsId(s.getGoodsId());
                erpOrderGoodsQuery.setGoodsSkuId(s.getGoodsSkuId());
                erpOrderGoodsQuery.setQty(s.getQty());
                erpOrderGoodsQuery.setPrice(DataUtils.fromYuanToFen(DataUtils.scale(s.getPrice(), 2, ROUND_HALF_UP)));
                erpOrderGoodsQueries.add(erpOrderGoodsQuery);
            });
            query1.setQueries(erpOrderGoodsQueries);
            ResponseResult<List<CouponGoodsDTO>> responseResult = marketingFeignClient.queryCouponGoodsRelation(query1);
            if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
                throw new BusinessException("查询商品和券关系失败");
            }
            Map<Long, List<CouponGoodsDTO>> collect = responseResult.getData().stream().collect(Collectors.groupingBy(CouponGoodsDTO::getGoodsSkuId));
            orderAmountQuery.getGoodsSkus().stream().filter(s -> collect.containsKey(s.getGoodsSkuId()))
                    .forEach(s -> s.setCouponCodes(collect.get(s.getGoodsSkuId()).stream().map(CouponGoodsDTO::getCouponCode).distinct().collect(Collectors.toList())));
        }
        //券code顺序保持一致处理
        List<OrderGoodsQuery> goodsSkus = orderAmountQuery.getGoodsSkus();
        List<Long> couponCodes = query.getCouponCodes();
        if (Collections3.isNotEmpty(goodsSkus) && Collections3.isNotEmpty(couponCodes)) {
            goodsSkus.forEach(x -> {
                List<Long> couponCodesNew = new ArrayList<>();
                List<Long> couponCodesTemp = x.getCouponCodes();
                if (Collections3.isNotEmpty(couponCodesTemp)) {
                    for (Long couponCode : couponCodes) {
                        if (couponCodesTemp.contains(couponCode)) {
                            couponCodesNew.add(couponCode);
                        }
                    }
                }
                x.setCouponCodes(couponCodesNew);
            });
        }
        ResponseResult<OrderAmountDTO> responseResult = orderFeignClient.queryAmount(orderAmountQuery);
        if (null == responseResult || null == responseResult.getData()) {
            throw new BusinessException("订单金额查询失败");
        }
        return responseResult.getData();
    }

    @Override
    public OrderAddResultDTO addOrder(OrderAddParam param) {
        com.ibeeking.found.open.api.common.param.OrderAddParam orderAddParam = JsonUtils.fromJson(param, com.ibeeking.found.open.api.common.param.OrderAddParam.class);
        orderAddParam.setShopId(systemServiceImpl.queryShopIdByShopCode(param.getShopCode()));
        orderAddParam.setMemberId(param.getMemberId());
        if (null != param.getMemberId() && !Collections3.isEmpty(param.getCouponCodes())) {
            CouponGoodsQuery query1 = new CouponGoodsQuery();
            query1.setMemberId(param.getMemberId());
            query1.setCouponCodes(param.getCouponCodes());
            List<ErpOrderGoodsQuery> erpOrderGoodsQueries = new ArrayList<>();
            param.getGoodsSkus().forEach(s -> {
                ErpOrderGoodsQuery erpOrderGoodsQuery = new ErpOrderGoodsQuery();
                erpOrderGoodsQuery.setChannel(GoodsChannelEnum.POS.getValue());
                erpOrderGoodsQuery.setShopId(orderAddParam.getShopId());
                erpOrderGoodsQuery.setGoodsId(s.getGoodsId());
                erpOrderGoodsQuery.setGoodsSkuId(s.getGoodsSkuId());
                erpOrderGoodsQuery.setQty(s.getQty());
                erpOrderGoodsQuery.setPrice(DataUtils.fromYuanToFen(DataUtils.scale(s.getPrice(), 2, ROUND_HALF_UP)));
                erpOrderGoodsQueries.add(erpOrderGoodsQuery);
            });
            query1.setQueries(erpOrderGoodsQueries);
            ResponseResult<List<CouponGoodsDTO>> responseResult = marketingFeignClient.queryCouponGoodsRelation(query1);
            if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
                throw new BusinessException("查询商品和券关系失败");
            }
            Map<Long, List<CouponGoodsDTO>> collect = responseResult.getData().stream().collect(Collectors.groupingBy(CouponGoodsDTO::getGoodsSkuId));
            orderAddParam.getGoodsSkus().stream().filter(s -> collect.containsKey(s.getGoodsSkuId()))
                    .forEach(s -> s.setCouponCodes(collect.get(s.getGoodsSkuId()).stream().map(CouponGoodsDTO::getCouponCode).distinct().collect(Collectors.toList())));
        }
        //券code顺序保持一致处理
        List<OrderGoodsParam> goodsSkus = orderAddParam.getGoodsSkus();
        List<Long> couponCodes = param.getCouponCodes();
        if (Collections3.isNotEmpty(goodsSkus) && Collections3.isNotEmpty(couponCodes)) {
            goodsSkus.forEach(x -> {
                List<Long> couponCodesNew = new ArrayList<>();
                List<Long> couponCodesTemp = x.getCouponCodes();
                if (Collections3.isNotEmpty(couponCodesTemp)) {
                    for (Long couponCode : couponCodes) {
                        if (couponCodesTemp.contains(couponCode)) {
                            couponCodesNew.add(couponCode);
                        }
                    }
                }
                x.setCouponCodes(couponCodesNew);
            });
        }
        ResponseResult<OrderAddResultDTO> responseResult = orderFeignClient.add(orderAddParam);
        if (null == responseResult || null == responseResult.getData()) {
            throw new BusinessException("订单新增失败");
        }
        OrderAddResultDTO data = responseResult.getData();
        if (Collections3.isEmpty(responseResult.getData().getPromotions())) {
            data.setPromotions(Collections3.emptyList());
        }
        return data;
    }

    @Override
    public OrderChargebackDTO queryChargeback(OrderChargebackQuery query) {
        query.setShopId(systemServiceImpl.queryShopIdByShopCode(query.getShopCode()));
        ResponseResult<OrderChargebackDTO> responseResult = orderFeignClient.queryChargeback(query);
        if (null == responseResult || null == responseResult.getData()) {
            OrderChargebackDTO result = new OrderChargebackDTO();
            result.setStatus(false);
            return result;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean orderChargeback(OrderChargebackParam param) {
        param.setShopId(systemServiceImpl.queryShopIdByShopCode(param.getShopCode()));
        ResponseResult<Boolean> responseResult = orderFeignClient.chargeback(param);
        if (null == responseResult || null == responseResult.getData()) {
            return false;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean cancelChargeback(OrderChargebackParam param) {
        param.setShopId(systemServiceImpl.queryShopIdByShopCode(param.getShopCode()));
        ResponseResult<Boolean> responseResult = orderFeignClient.cancelChargeback(param);
        if (null == responseResult || null == responseResult.getData()) {
            return false;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean successChargeback(OrderChargebackParam param) {
        param.setShopId(systemServiceImpl.queryShopIdByShopCode(param.getShopCode()));
        ResponseResult<Boolean> responseResult = orderFeignClient.successChargeback(param);
        if (null == responseResult || null == responseResult.getData()) {
            return false;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean savePayType(List<ErpPayTypeParam> params) {
        ResponseResult<Boolean> responseResult = orderFeignClient.savePayType(params);
        if (null == responseResult || null == responseResult.getData()) {
            return false;
        }
        return responseResult.getData();
    }
}
